package com.yqh.Collection.Set;

import lombok.*;

import java.util.Set;
import java.util.TreeSet;

/**
 * TreeSet 集合的底层原理
 *
 * @author 阳秋豪
 * @createTime 2024/3/6
 */
public class Test3 {
    public static void main(String[] args) {
        /*-----------------TreeSet 集合的底层原理-----------------*/
        // 1、特点：不重复、无索引、可排序(默认升序排序按照元素的大小，由小到大排序

        // 2、底层：基于红黑树实现的排序

        // 3、注意
        // -- 对于数值类型：Integer，Double，默认按照数值本身的大小进行升序排序
        // -- 对于字符串类型：默认按照首字符的编号升序排序
        // -- 对于自定义类型如Student对象，TreeSet 默认是无法直接排序的（会报异常）

        // 4、自定义排序规则
        //-- TreeSet集合存储自定义类型的对象时，必须指定排序规则，支持如下两种方式来指定比较规则。
        //-- 方式1：让自定义的类(如学生类)实现 Comparable 接口，重写里面的 compareTo 方法来指定比较规则，
        Set<Student> set = new TreeSet<>();
        set.add(new Student("张三", 21));
        set.add(new Student("李四", 25));
        set.add(new Student("假四", 25));
        set.add(new Student("王五", 20));
        set.add(new Student("赵六", 27));
        System.out.println("按年龄从小到大排序 -- " + set); // 按年龄从小到大排序 -- [{王五,20}, {张三,21}, {李四,25}, {赵六,27}]

        //-- 方式2：通过调用 TreeSet 集合有参数构造器，可以设置 Comparator 对象（比较器对象，用于指定比较规则）
        /*Set<Student> set1 = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        }); 完整写法*/
        Set<Student> set1 = new TreeSet<>((o1, o2) -> o1.getAge() - o2.getAge()); // 简化写法
        set1.add(new Student("张三", 21));
        set1.add(new Student("李四", 25));
        set1.add(new Student("假四", 25));
        set1.add(new Student("王五", 20));
        set1.add(new Student("赵六", 27));
        System.out.println("按年龄从小到大排序 -- " + set1); // 按年龄从小到大排序 -- [{王五,20}, {张三,21}, {李四,25}, {赵六,27}]

        /*----------------------------- 问题 -----------------------------*/
        // 问题：上述自定义排序中为什么假四没有存进去
        // 答：因为TreeSet是按照特定属性是否相等判断是否是同一对象，后添加的对象将被舍弃。案例中特定属性是年龄age，而假四跟李四年龄相等了并且李四先存了所以导致假四被舍弃
    }
}

@AllArgsConstructor
@Getter
@EqualsAndHashCode
class Student implements Comparable<Student> {
    private String name;
    private int age;

    @Override
    public int compareTo(Student o) {
        return age - o.getAge();
    }

    @Override
    public String toString() {
        return "{" + name + "," + age + '}';
    }
}

@AllArgsConstructor
@Getter
@EqualsAndHashCode
class Student1 {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "{" + name + "," + age + '}';
    }
}
